package cn.hls.dao.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import cn.hls.dao.ACLDao;
import cn.hls.entity.ACL;
import cn.hls.entity.ACLExt;
import cn.hls.entity.Module;

/**
 * @fileName: ACLDaoImpl.java
 * @descrption: ACL权限接口实现类
 * @author : yinghui.zhang
 * @Email: uuhui@163.com
 * @date 2015-4-8
 * @version 1.0
 */
@Component("aclDaoImpl")
public class ACLDaoImpl extends BaseDaoImpl<ACL> implements ACLDao {

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public List searchAclRecord(Integer principalType, Long principalId,
			Long moduleId) throws Exception {
		String hql = "select moduleId,aclState,aclTriState,id from ACL where principalType = ? and principalId = ? and moduleId = ? and deleted = ?";
		List resultList = new ArrayList();
		List parentlist = new ArrayList();
		List elist = new ArrayList();
		List tempList = findByHql(hql, new Object[] { principalType,
				principalId, moduleId, false });
		if ((tempList != null) && (!tempList.isEmpty())) {
			Object[] obj = (Object[]) tempList.get(0);
			parentlist
					.add(Long.valueOf(Long.valueOf(obj[0].toString())));
			int aclState = Integer.parseInt(obj[1].toString());
			int maxint = Integer.MAX_VALUE;
			int l = Integer.toBinaryString(maxint).length();
			for (int i = 0; i < l; i++) {
				int temp = 1;
				temp <<= i;
				int ii = maxint & temp;
				parentlist.add(Integer.valueOf(aclState & temp));
			}
			parentlist
					.add(Integer.valueOf(Integer.parseInt(obj[2].toString())));
			String tl = "from ACLExt where aclId =?";
			elist = findByHql(tl,
					new Object[] { Long.valueOf(obj[3].toString()) });
		}
		resultList.add(parentlist);
		resultList.add(elist);
		return resultList;
	}

	@Override
	public void addOrUpdatePermission(Integer principalType,
			Long principalId, Long moduleId, Integer permission,
			boolean yes) throws Exception {
		// 根据主体标识和资源标识查找ACL实例
		ACL acl = findACL(principalType, principalId, moduleId);
		if (acl != null) {
			acl.setPermission(permission, yes);
			//getHibernateTemplate().update(acl);
			update(acl);
			return;
		}
		acl = new ACL();
		acl.setPrincipalType(principalType);
		acl.setPrincipalId(principalId);
		acl.setModuleId(moduleId);
		acl.setPermission(permission, yes);
		//getHibernateTemplate().save(acl);
		acl.setId(super.getCustomerId());
		add(acl);
	}

	@Override
	public void addOrUpdateExtPermission(Integer principalType,
			Long principalId, Long moduleId, String ex) throws Exception {
		// 根据主体类型、主体标、模块标识查询Acl信息
		ACL acl = findACL(principalType, principalId, moduleId);
		if (acl != null) {
			acl.setAclExtState(0);// 设置扩展授权
		} else {// 不存在创建
			acl = new ACL();
			acl.setPrincipalType(principalType);
			acl.setPrincipalId(principalId);
			acl.setModuleId(moduleId);
			//getHibernateTemplate().save(acl);
			add(acl);
		}

		String hql = "delete from ACLExt where aclId =?";
		executeHQLUpdate(hql, new Object[] { acl.getId() });
		if ((ex != null) && (!ex.equals(""))) {
			String[] exp = ex.split(",");
			for (String e : exp) {
				String[] dn = e.split("\\|");
				acl.setExtPermission(Integer.parseInt(dn[0]), true);
				ACLExt tx = new ACLExt();
				tx.setAclId(acl.getId());
				tx.setOprExt(Integer.valueOf(Integer.parseInt(dn[0])));
				tx.setOprName(dn[1]);
				//getHibernateTemplate().save(tx);
				getSession().save(tx);
			}
		}
	}

	@Override
	public void updateEnable(Integer principalType, Long principalId,
			Long moduleId, boolean yes) throws Exception {
		ACL acl = findACL(principalType, principalId, moduleId);
		if (acl != null) {
			if (yes)
				acl.setAclTriState(0);
			else
				acl.setAclTriState(1);
			//getHibernateTemplate().update(acl);
			update(acl);
			return;
		}
	}

	@Override
	public ACL findACL(Integer principalType, Long principalId,
			Long moduleId) throws Exception {
		Query q = getSession()
				.createQuery(
						"select acl from ACL acl where acl.principalType = ? and acl.principalId=? and acl.moduleId = ? and acl.deleted = false")
				.setParameter(0, principalType).setParameter(1, principalId)
				.setParameter(2, moduleId);
		q.setCacheable(true);
		return (ACL) q.uniqueResult();
	}

	@SuppressWarnings("static-access")
	@Override
	public void addOrUpdateUserEnable(Long userId, Long moudleId,
			Integer yes) throws Exception {
		// 根据主体标识和资源标识查找ACL实例
		ACL acl = findACL(ACL.TYPE_USER, userId, moudleId);
		if (acl != null) {
			acl.setAclTriState(yes);
			//getHibernateTemplate().update(acl);
			update(acl);
			return;
		}
		acl = new ACL();
		acl.setPrincipalType(acl.TYPE_USER);
		acl.setPrincipalId(userId);
		acl.setModuleId(moudleId);
		acl.setAclTriState(yes);
		//getHibernateTemplate().save(acl);
		add(acl);
	}

	@Override
	public List<Module> searchModules(Long userId) throws Exception {
		List<Module> hasRUModules = getSelfACLModule(userId);
		if (!hasRUModules.isEmpty()) {
			return hasRUModules;
		}
		return getRoleOrgACLModule(userId);
	}

	/**
	 * 根据用户编号获取模块信息
	 * 
	 * @param userId
	 *            用户编号
	 * @return List<Module>
	 * @throws Exception
	 *             异常
	 */
	private List<Module> getSelfACLModule(Long userId) throws Exception {

		StringBuilder selectHql = new StringBuilder(
				"select new cn.hls.entity.Module(m.id,m.name,m.url,m.expend,m.parent.id,a.aclState) ");
		selectHql
				.append("from ACL a,Module m where m.id = a.moduleId and a.principalType = ?  and a.principalId = ? and a.aclTriState =? ");
		selectHql.append("and a.deleted=? and m.deleted=? order by m.sort");
		return getPermissionModule(selectHql.toString(), new Object[] {
				ACL.TYPE_USER, userId, 0, false, false });
	}

	private List<Module> getRoleOrgACLModule(Long userId) throws Exception {
		StringBuilder selecRoletHql = new StringBuilder(
				"select new cn.hls.entity.Module(m.id,m.name,m.url,m.expend,m.parent.id,a.aclState) ");
		selecRoletHql
				.append("from ACL a,Module m where a.moduleId = m.id and a.aclTriState = 0 and a.principalType =? ");
		selecRoletHql
				.append("and a.principalId in (select ur.role.id from UserRole ur where ur.user.id =?) ");
		selecRoletHql.append("and a.deleted=? and m.deleted=? order by m.sort");
		List<Module>list=getPermissionModule(selecRoletHql.toString(), new Object[] {
				ACL.TYPE_ROLE, userId, false, false });
		if (list.isEmpty()) {
			StringBuilder selectOrgHql = new StringBuilder(
					"select new cn.hls.entity.Module(m.id,m.name,m.url,m.expend,m.parent.id,a.aclState) ");
			selectOrgHql
					.append("from ACL a,Module m where m.id = a.moduleId and a.aclTriState = ? and a.principalType =? ");
			selectOrgHql
					.append("and a.principalId in (select u.person.org.id from User u where u.id =?) and a.deleted=? ");
			selectOrgHql.append("and m.deleted=? order by m.sort");
			list=getPermissionModule(selectOrgHql.toString(), new Object[] { 0,
					ACL.TYPE_ORG, userId, false, false });
		}
		return list;
	}

	/**
	 * 获取模块信息并设置模块的权限
	 * 
	 * @param hql
	 *            hql查询语句
	 * @param params
	 *            查询参数
	 * @param list
	 *            返回的数据集合
	 * @throws Exception
	 *             异常
	 */
	@SuppressWarnings("unchecked")
	private List<Module> getPermissionModule(String hql, Object[] params)
			throws Exception {
		// list = findByHql(hql, params);
		// setPermissionModule(tempList, list);
		Query query = getSession().createQuery(hql);
		for (int i = 0; i < params.length; i++) {
			query.setParameter(i, params[i]);
		}
		/*
		 * for(Object obj:list){ Module m=(Module)obj;
		 * System.out.println("id:"+m.getId() +" name:"+m.getName());
		 * 
		 * }
		 */
		return (List<Module>) query.list();
	}

	@Override
	public void delPermission(Integer principalType, Long principalId)
			throws Exception {
		String hql = "delete ACL   where principalType = ? and principalId = ?";
		executeHQLUpdate(hql, new Object[] { principalType, principalId });
	}

	@Override
	public void delPermission(Integer principalType, Long principalId,
			Long moduleId) throws Exception {
		//getHibernateTemplate().delete(findACL(principalType, principalId, moduleId));
			getSession().delete(findACL(principalType, principalId, moduleId));	

	}

	@Override
	public boolean isAclExists(Long moduleId) throws Exception {
		String hql = "select count(id) from ACL acl where acl.moduleId = ? ";
		Query query = getSession().createQuery(hql);
		query.setParameter(0, moduleId);
		int count = ((Long) query.uniqueResult()).intValue();
		if (count > 0) {
			return true;
		}
		return false;
	}

	@Override
	public boolean hasPermissionByResourceCode(Long userId,
			String moduleCode, int permissionExt) throws Exception {
		return hasPermissionByResourceCode(userId, moduleCode, permissionExt,
				true);
	}

	@SuppressWarnings("unused")
	@Override
	public boolean hasPermissionByResourceCode(Long userId,
			String moduleCode, int permissionExt, boolean sys) throws Exception {
		String personRight = null;
		String roleRight = "1";
		String orgRight = null;
		String type = "aclState";
		if (!sys) {
			type = "aclExtState";
		}

		if ((personRight != null) && (personRight.equals("1"))) {
			String hql = "select a."
					+ type
					+ " from ACL a,Module m where m.id = a.moduleId and a.principalType = ?  "
					+ "and a.principalId = ? and a.aclTriState = 0 and  m.code = ? and a.deleted=false and m.deleted=false ";

			return permissionResource(hql, new Object[] { ACL.TYPE_USER,
					userId, moduleCode }, permissionExt, sys);
		}

		if (roleRight.equals("1")) {
			String hql = "select a."
					+ type
					+ " from ACL a,Module m where a.moduleId = m.id and "
					+ "a.aclTriState = ? and a.principalType =? and a.principalId in "
					+ "(select ur.role.id from UserRole ur where ur.user.id =?) and m.code = ? and a.deleted=false and m.deleted=false";

			return permissionResource(hql, new Object[] { 0, ACL.TYPE_ROLE,
					userId, moduleCode }, permissionExt, sys);
		}

		if ((orgRight != null) && (orgRight.equals("1"))) {
			String hql = "select a."
					+ type
					+ " from ACL a,Module m where m.id = a.moduleId and a.aclTriState = ? and a.principalType =? "
					+ "and a.principalId in (select u.person.orgId from User u where u.id =?) "
					+ "and m.code = ? and a.deleted=false and m.deleted=false";

			return permissionResource(hql, new Object[] { 0, ACL.TYPE_ORG,
					userId, moduleCode }, permissionExt, sys);
		}

		return false;
	}

	@SuppressWarnings("rawtypes")
	private boolean permissionResource(String hql, Object[] params,
			int permissionExt, boolean sys) throws Exception {
		List list = findByHqlWithCache(hql, params);
		Iterator iterator = null;
		if ((list != null) && (!list.isEmpty())) {
			for (iterator = list.iterator(); iterator.hasNext();) {
				Object obj = iterator.next();
				if ((obj != null) && (!obj.equals(""))) {
					ACL acl = new ACL();
					acl.setAclTriState(0);
					if (sys) {
						acl.setAclState(Integer.parseInt(obj.toString()));
						return acl.getPermission(permissionExt) == 1;
					}
					acl.setAclExtState(Integer.parseInt(obj.toString()));
					return acl.getExtPermission(permissionExt) == 1;
				}

			}

		}

		return false;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public List findByCode(String code) throws Exception {
		// 定义查询hql
		StringBuilder selectHql = new StringBuilder(
				" from Module f where deleted=? ");
		// 定义查询参数
		List<Object> paramList = new ArrayList<Object>();
		paramList.add(false);
		if (StringUtils.hasText(code)) {
			selectHql.append(" and f.code = ? ");
			paramList.add(code);
		}
		return findByHqlWithCache(selectHql.toString(), paramList.toArray());
	}

	@Override
	public void deleteAclByModule(Long moduleId) throws Exception {
		String hql = "delete ACL   where moduleId=?";
		executeHQLUpdate(hql, new Object[] {  moduleId });
	}
}
